<!DOCTYPE html>



  


<html class="theme-next gemini use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />







<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.4" rel="stylesheet" type="text/css" />


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="unix,笔记," />










<meta name="description" content="函数stat、fstat、fstatat和lstat1234567#include &lt;sys&#x2F;stat.h&gt;int stat(const char *restrict pathname, struct stat *restrict buf);int fstat(int fd, struct stat *buf);int lstat(const char* restrict pathna">
<meta property="og:type" content="article">
<meta property="og:title" content="unix环境高级编程：文件和目录">
<meta property="og:url" content="http://liuyun000.gitee.io/2019/10/29/unix/unix%E7%8E%AF%E5%A2%83%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%EF%BC%9A%E6%96%87%E4%BB%B6%E5%92%8C%E7%9B%AE%E5%BD%95/index.html">
<meta property="og:site_name" content="liuyun的博客">
<meta property="og:description" content="函数stat、fstat、fstatat和lstat1234567#include &lt;sys&#x2F;stat.h&gt;int stat(const char *restrict pathname, struct stat *restrict buf);int fstat(int fd, struct stat *buf);int lstat(const char* restrict pathna">
<meta property="article:published_time" content="2019-10-29T00:02:44.000Z">
<meta property="article:modified_time" content="2019-11-21T05:15:40.343Z">
<meta property="article:author" content="liuyun">
<meta property="article:tag" content="unix">
<meta property="article:tag" content="笔记">
<meta name="twitter:card" content="summary">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Gemini',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="http://liuyun000.gitee.io/2019/10/29/unix/unix环境高级编程：文件和目录/"/>





  <title>unix环境高级编程：文件和目录 | liuyun的博客</title>
  








<meta name="generator" content="Hexo 4.2.0"></head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">liuyun的博客</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
            
            标签
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives/%20" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://liuyun000.gitee.io/2019/10/29/unix/unix%E7%8E%AF%E5%A2%83%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%EF%BC%9A%E6%96%87%E4%BB%B6%E5%92%8C%E7%9B%AE%E5%BD%95/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="liuyun">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="liuyun的博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">unix环境高级编程：文件和目录</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              
              <time title="创建于" itemprop="dateCreated datePublished" datetime="2019-10-29T08:02:44+08:00">
                2019-10-29
              </time>
            

            

            
          </span>

          
            <span class="post-category" >
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/unix%E7%8E%AF%E5%A2%83%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B/" itemprop="url" rel="index">
                    <span itemprop="name">unix环境高级编程</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h3 id="函数stat、fstat、fstatat和lstat"><a href="#函数stat、fstat、fstatat和lstat" class="headerlink" title="函数stat、fstat、fstatat和lstat"></a>函数stat、fstat、fstatat和lstat</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sys/stat.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">stat</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *<span class="keyword">restrict</span> pathname, struct stat *<span class="keyword">restrict</span> buf)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">fstat</span><span class="params">(<span class="keyword">int</span> fd, struct stat *buf)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">lstat</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span>* <span class="keyword">restrict</span> pathname, struct stat* <span class="keyword">restrict</span> buf)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">fstatat</span><span class="params">(<span class="keyword">int</span> fd, <span class="keyword">const</span> <span class="keyword">char</span> *<span class="keyword">restrict</span> pathname, struct stat *<span class="keyword">restrict</span> buf, <span class="keyword">int</span> flag)</span></span>;</span><br><span class="line"><span class="comment">/* 所有四个函数的返回值：若成功：返回0；若出错：返回-1 */</span></span><br></pre></td></tr></table></figure>

<p>  一旦给出pathname，    </p>
<ul>
<li>stat函数将返回与此命名文件有关的信息结构；  </li>
</ul>
<ul>
<li>fstat函数获得已在描述符fd上打开文件的相关信息。</li>
</ul>
<ul>
<li>lstat函数类似于stat，但是当命名文件是一个符号链接时，lstat返回该符号链接的有关信息，而不是由该符号链接引用的文件的信息。</li>
</ul>
<ul>
<li>fstatat函数为一个相对于当前目录（由fd指定）的路径名返回文件信息。flag参数控制着是否跟随着一个符号链接。当AT_SYMLINK_NOFOLLOW标志被设置时，fstatat不会跟随符号链接，而是返回符号链接本身的信息。否则，在默认情况下，返回的是符号链接所指向的实际文件的信息。如果fd参数的值是AT_FDCWD，并且pathname参数是一个相对路径名，fstatat会计算相对于当前目录的pathname参数。如果pathname是一个绝对路径，fd参数就会被忽略。在这两种情况下，根据flag的取值，fstatat的作用就跟stat或lstat一样。  </li>
</ul>
<p>stat结构：  </p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">stat</span> &#123;</span></span><br><span class="line">    <span class="keyword">mode_t</span>					st_mode;	<span class="comment">/*file type &amp; mode (permissions)*/</span></span><br><span class="line">    <span class="keyword">ino_t</span>					st_ino;		<span class="comment">/*i-node number (serial number)*/</span></span><br><span class="line">    <span class="keyword">dev_t</span>					st_dev;		<span class="comment">/*device number (file system)*/</span></span><br><span class="line">    <span class="keyword">dev_t</span>					st_rdev;	<span class="comment">/*device number for special files*/</span></span><br><span class="line">    <span class="keyword">nlink_t</span>					st_nlink;	<span class="comment">/*number of links*/</span></span><br><span class="line">    <span class="keyword">uid_t</span>					st_uid;		<span class="comment">/*user id of owner*/</span></span><br><span class="line">    <span class="keyword">gid_t</span>					st_gid;		<span class="comment">/*group id of owner*/</span></span><br><span class="line">    <span class="keyword">off_t</span>					st_size;	<span class="comment">/*size in bytes, for regular files*/</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">timespec</span>			<span class="title">st_atime</span>;</span>	<span class="comment">/*time of last access*/</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">timespec</span>			<span class="title">st_mtime</span>;</span>	<span class="comment">/*time of last amodification*/</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">timespec</span>			<span class="title">st_ctime</span>;</span>	<span class="comment">/*time of last file stats change*/</span></span><br><span class="line">    <span class="keyword">blsize_t</span>				st_blsize;	<span class="comment">/*best I/O block size*/</span></span><br><span class="line">    <span class="keyword">blcnt_t</span>					st_blocks;	<span class="comment">/*number of disk blocks allocated*/</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>POSIX.1 未要求st_rdev、st_blsize和st_blocks 字段。SUS XSI扩展定义了这些字段。</p>
</blockquote>
<p>timespec结构类型按照秒和纳秒定义了时间，至少包括下面两个字段。</p>
<ul>
<li>time_t    tv_sec;</li>
<li>long        tv_nsec;</li>
</ul>
<h3 id="文件类型"><a href="#文件类型" class="headerlink" title="文件类型"></a>文件类型</h3><ol>
<li><p>普通文件(regular file)。这是最常用的文件类型，这种文件包含了某种形式的数据。至于这种数据是文本还是二进制数据，对于UNIX内核而言并无区别。对普通文件内容的解释由处理该文件的应用程序进行。</p>
</li>
<li><p>目录文件(directory file)。这种文件包含了其他文件的名字以及指向与这些有关信息的指针。对一个目录文件具有读权限的任意进程都可以读该目录的内容，但只有内核可以直接写目录文件。进程必须使用系统调用才能更改目录。</p>
</li>
<li><p>块特殊文件(block special file)。这种类型的文件提供对设备（如磁盘）带缓冲的访问，每次访问以固定长度为单位进行。</p>
</li>
<li><p>字符特殊文件(character special file)。这种类型的文件提供对是被不带缓冲的访问，每次访问长度可变。系统中的所有设备要么是字符特殊文件，要么是块特殊文件。</p>
</li>
<li><p>FIFO。这种类型的文件用于进程间通信，又是也称为命名管道(named pipe)。</p>
</li>
<li><p>套接字(socket)。这种类型的文件用于进程间的网络通信。套接字特可用于在一台宿主机上进程之间的非网络通信。</p>
</li>
<li><p>符号链接(symbolic link)。这种类型的文件指向另一个文件。</p>
</li>
</ol>
<p>文件类型信息包含在stat结构的st_mode成员中。可以用下表中的宏确定文件类型。这些宏的参数都是stat结构中的st_mode成员。</p>
<table>
<thead>
<tr>
<th>宏</th>
<th>文件类型</th>
</tr>
</thead>
<tbody><tr>
<td>S_ISREG()</td>
<td>普通文件</td>
</tr>
<tr>
<td>S_ISDIR()</td>
<td>目录文件</td>
</tr>
<tr>
<td>S_ISCHR()</td>
<td>字符特殊文件</td>
</tr>
<tr>
<td>S_ISBLK()</td>
<td>块特殊文件</td>
</tr>
<tr>
<td>S_ISFIFO()</td>
<td>管道或FIFO</td>
</tr>
<tr>
<td>S_ISLNK()</td>
<td>符号链接</td>
</tr>
<tr>
<td>S_ISSICK()</td>
<td>套接字</td>
</tr>
</tbody></table>
<p>POSIX.1 允许实现将进程间通信(IPC)对象（如详细队列和信号量等）说明为文件。下表中的宏可用来从stat结构中确定IPC对象的类型。这些宏与表中的不同，他们的参数并非st_mode，而是指向stat结构的指针。    </p>
<table>
<thead>
<tr>
<th>宏</th>
<th>对象的类型</th>
</tr>
</thead>
<tbody><tr>
<td>S_TYPEISMQ()</td>
<td>消息队列</td>
</tr>
<tr>
<td>S_TYPEISSEM()</td>
<td>信号量</td>
</tr>
<tr>
<td>S_TYPEISSHM()</td>
<td>共享存储对象</td>
</tr>
</tbody></table>
<h3 id="设置用户ID和组ID"><a href="#设置用户ID和组ID" class="headerlink" title="设置用户ID和组ID"></a>设置用户ID和组ID</h3><p>实际用户ID、实际组ID  =&gt; 我们实际上是谁；  </p>
<p>有效用户ID、有效组ID、附属组ID  =&gt; 用于文件访问权限检查；  </p>
<p>保存的设置用户ID、保存的设置组ID =&gt; 由exec函数保存。  </p>
<ul>
<li>实际用户和实际组ID标示我们究竟是谁。这两个字段在登陆时取自空灵文件中的登陆项。通常，在一个登录会话期间这些值并不改变，但是超级用户进程有方法改变它他们。  </li>
<li>有效用户ID、有效组ID以及附属组ID决定了我们的文件访问权限。</li>
<li>保存的设置用户ID和保存的设置组ID在执行一个程序时包含了有效用户ID和有效组ID的副本。  </li>
</ul>
<h3 id="文件访问权限"><a href="#文件访问权限" class="headerlink" title="文件访问权限"></a>文件访问权限</h3><p>st_mode值也包含了对文件的访问权限位。当提及文件时，指的是前面所提到的任何类型的文件。所有文件类型（目录、字符特殊文件等）都有访问权限（accsee permission）。  </p>
<p>每个文件有9个访问权限位，可将他们分成3类。见下表（取自&lt;sys/stat.h&gt;）。  </p>
<table>
<thead>
<tr>
<th>st_mode屏蔽</th>
<th>含义</th>
</tr>
</thead>
<tbody><tr>
<td>S_IRUSR</td>
<td>用户读</td>
</tr>
<tr>
<td>S_IWUSR</td>
<td>用户写</td>
</tr>
<tr>
<td>S_IXUSR</td>
<td>用户执行</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td>S_IRGRP</td>
<td>组读</td>
</tr>
<tr>
<td>S_IWGRP</td>
<td>组写</td>
</tr>
<tr>
<td>S_IXGRP</td>
<td>组执行</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td>S_IROTH</td>
<td>其他读</td>
</tr>
<tr>
<td>S_IWOTH</td>
<td>其他写</td>
</tr>
<tr>
<td>S_XOTH</td>
<td>其他执行</td>
</tr>
</tbody></table>
<p>​    </p>
<p>在上表前三行中，术语用户指的是文件所有者(owner)。chmod命令用于修改这9个权限位。该命令允许我们用u表示用户（所有者），用g表示组，用o表示其他。    </p>
<p>上表中的3类访问权限（即读、写和执行）以各种方式由不同的函数使用。其汇总如下：  </p>
<ul>
<li>第一个规则是，我们用名字打开任一类型的文件时，对该名字中包含的每一个目录，包括它可能隐含的当前工作目录都应具有执行权限。这就是为什么对于目录其执行权限位常被称为搜索位的原因。  </li>
<li>对一个文件的读权限决定了我们是否能够打开现有文件进行读操作。这与open函数的O_RDONLY和O_RDWR标志相关。</li>
<li>对于一个文件的写权限决定了我们是否能够打开现有文件进行写操作。这与open函数的O_WDONLY和O_RDWR标志相关。</li>
<li>为了在open函数中对一个文件指定O_TRUNC标志，必须对该文件具有写权限。</li>
<li>为了在一个目录中创建一个新文件，必须对该目录具有写权限和执行权限。</li>
<li>为了删除一个现有文件，必须对包含该文件的目录具有写权限和执行权限。对该文件本身不需要有读、写权限。</li>
<li>如果用7个exec函数中的任何一个执行某个文件，都必须对该文件具有执行权限。该文件还必须是一个普通文件。</li>
</ul>
<h3 id="新文件和目录的所有权"><a href="#新文件和目录的所有权" class="headerlink" title="新文件和目录的所有权"></a>新文件和目录的所有权</h3><p>新文件的用户ID设置文进程的有效用户ID。关于组ID, POSIX.1允许实现选择下列之一作为新文件的组ID。  </p>
<ol>
<li>新文件的组ID可以是进程的有效组ID。</li>
<li>新文件的组ID可以是它所在目录的组ID。</li>
</ol>
<p>使用POSIX.1所允许的第二个选项（继承目录的组ID）使得在某个目录下创建的文件和目录都具有该目录的组ID。于是文件和目录的所有权从该店向下传递。  </p>
<h3 id="函数access和faccessat"><a href="#函数access和faccessat" class="headerlink" title="函数access和faccessat"></a>函数access和faccessat</h3><p>access和faccessat函数是按实际用户ID和实际组ID进行权限测试的。  </p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">access</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *pathname, <span class="keyword">int</span> mode)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">faccessat</span><span class="params">(<span class="keyword">int</span> fd, <span class="keyword">const</span> <span class="keyword">char</span> *pathname, <span class="keyword">int</span> mode, <span class="keyword">int</span> flag)</span></span>;</span><br><span class="line"><span class="comment">/*两个函数的返回值：若成功，返回0；若出错，返回-1*/</span></span><br></pre></td></tr></table></figure>



<p>其中，如果测试文件是否已经存在，mode就为F_OK；否则mode就是下表中所列常量的按位或。</p>
<table>
<thead>
<tr>
<th>mode</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>R_OK</td>
<td>测试读权限</td>
</tr>
<tr>
<td>W_OK</td>
<td>测试写权限</td>
</tr>
<tr>
<td>X_OK</td>
<td>测试执行权限</td>
</tr>
</tbody></table>
<p>faccessat函数与access在下面两个情况下是相同的：一种是pathname参数位绝对路径，另一种是fd参数取值为AT_FDCWD而pathname参数为相对路径。负责，faccessat计算相对于打开目录（由fd参数指向）的pathname。  </p>
<p>flag参数可以用于改变facessat的行为，如果flag设置为AT_EACESS，访问检查用的是调用进程的有效用户ID和有效组ID，而不是实际用户ID和实际组ID。</p>
<h3 id="函数umask"><a href="#函数umask" class="headerlink" title="函数umask"></a>函数umask</h3><p>umask函数为进程设置文件模式创建屏蔽字，并返回之前的值。（没有出错返回）</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sy/stat.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">mode_t</span> <span class="title">umask</span><span class="params">(<span class="keyword">mode_t</span> cmask)</span></span>;</span><br><span class="line"><span class="comment">/* 返回值：之前的文件模式创建屏蔽字 */</span></span><br></pre></td></tr></table></figure>



<p>其中参数cmask是由S_IRUSER、S_IWUSR等9个常量中的若干个按位“或”构成的。  </p>
<h3 id="函数chmod、fchmod和fchmodat"><a href="#函数chmod、fchmod和fchmodat" class="headerlink" title="函数chmod、fchmod和fchmodat"></a>函数chmod、fchmod和fchmodat</h3><p>chmod、fchmod和fchmodat这3个函数使我们可以更改现有文件的访问权限。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sys/stat.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">chmod</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *pathname, <span class="keyword">mode_t</span> mode)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">fchmod</span><span class="params">(<span class="keyword">int</span> fd, <span class="keyword">mode_t</span> mode)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">fchmodat</span><span class="params">(<span class="keyword">int</span> fd, <span class="keyword">const</span> <span class="keyword">char</span> *pathname, <span class="keyword">mode_t</span> mode, <span class="keyword">int</span> flag)</span></span>;</span><br><span class="line"><span class="comment">/*3个函数返回值：若成功，返回0；若出错，返回-1*/</span></span><br></pre></td></tr></table></figure>



<p>为了改变一个文件的权限位，进程的有效用户ID必须等于文件的所有者ID，或者该进程必须具有娼妓用户权限。  </p>
<p>参数mode使下表常量的按位或。</p>
<table>
<thead>
<tr>
<th>mode</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>S_ISUID</td>
<td>执行时设置用户ID</td>
</tr>
<tr>
<td>S_ISGID</td>
<td>执行时设置组ID</td>
</tr>
<tr>
<td>S_ISVTX</td>
<td>保存正文（粘着位）</td>
</tr>
<tr>
<td>S_IRXU</td>
<td>用户（所有者）读、写、执行</td>
</tr>
<tr>
<td>S_IRUSR</td>
<td>用户（所有者）读</td>
</tr>
<tr>
<td>S_IWUSR</td>
<td>用户（所有者）写</td>
</tr>
<tr>
<td>S_IXUSR</td>
<td>用户（所有者）执行</td>
</tr>
<tr>
<td>S_IRWXG</td>
<td>组读、写、执行</td>
</tr>
<tr>
<td>S_IRGRP</td>
<td>组读</td>
</tr>
<tr>
<td>S_IWGRP</td>
<td>组写</td>
</tr>
<tr>
<td>S_IXGRP</td>
<td>组执行</td>
</tr>
<tr>
<td>S_IRWXO</td>
<td>其他读、写、执行</td>
</tr>
<tr>
<td>S_IROTH</td>
<td>其他读</td>
</tr>
<tr>
<td>S_IWOTH</td>
<td>其他写</td>
</tr>
<tr>
<td>S_IXOTH</td>
<td>其他执行</td>
</tr>
</tbody></table>
<h3 id="粘着位"><a href="#粘着位" class="headerlink" title="粘着位"></a>粘着位</h3><p>粘着位（stick bit）在早期表示程序退出时其正文仍保存在交换区，直至系统自举，后来的unix系统称其为保存正文位(saved-text bit)。  </p>
<p>现今的系统扩展了粘着位的使用范围，SUS允许针对目录设置粘着位。如果对一个目录设置了粘着位，只有对该目录具有写权限的用户且满足下列条件之一，才能删除或重命名该目录下的文件：  </p>
<ul>
<li>拥有此文件</li>
<li>拥有此目录</li>
<li>是超级用户</li>
</ul>
<h3 id="函数chown、fchown、fchownat和lchown"><a href="#函数chown、fchown、fchownat和lchown" class="headerlink" title="函数chown、fchown、fchownat和lchown"></a>函数chown、fchown、fchownat和lchown</h3><p>用于更改文件的用户ID和组ID，如果两个参数owner或group中的任意一个是-1，则对应ID不变。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">chown</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *pathname, <span class="keyword">uid_t</span> owner, <span class="keyword">gid_t</span> git)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">fchown</span><span class="params">(<span class="keyword">int</span> fd, <span class="keyword">uid_t</span> owner, <span class="keyword">gid_t</span> group)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">fchownat</span><span class="params">(<span class="keyword">int</span> fd, <span class="keyword">const</span> <span class="keyword">char</span> *pathname, <span class="keyword">uid_t</span> owner, <span class="keyword">gid_t</span> group, <span class="keyword">int</span> flag)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">lchown</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *pathname, <span class="keyword">uid_t</span> owner, <span class="keyword">gid_t</span> group)</span></span>;</span><br><span class="line"><span class="comment">/* 4个函数的返回值：若成功，返回0；若出错，返回-1 */</span></span><br></pre></td></tr></table></figure>



<p>除了所引用的文件是符号链接外，这4个函数的操作类似。在符号链接情况下，lchown和fchownat（设置了AT_SYMLINK_NOFOLLOW标志）更改符号链接本身的所有者，而不是该符号链接所指向的文件的所有者。</p>
<h3 id="文件长度"><a href="#文件长度" class="headerlink" title="文件长度"></a>文件长度</h3><p>stat结构成员st_size表示以字节为单位的文件的长度。此字段只对普通文件、目录文件和符号链接有意义。  </p>
<blockquote>
<p>FreeBSD 8.0、Mac OS X 10.6.8和Solaris 10对管道也定义了文件长度，它标志可从该管道中读到的字节数。</p>
</blockquote>
<p>对于普通文件，其文件长度可以是0，在开始读这种文件时，将得到文件结束(end-of-file)指示。对于目录，文件长度通常是一个数（如16或512）的整数倍。</p>
<p>对于符号链接，文件长度是在文件名中的实际字节数。</p>
<p>现今，大多数现代的UNXI系统提供字段st_blksize和st_blocks。其中，第一个是对文件I/O较合适的块长度，第二个是所分配的实际512字节块块数。当我们将st_blksize用于读操作时（即st_blksize作为缓冲区长度），读一个文件所需的时间量最少。为了提高效率，标准I/O库也试图一次读、写st_blksize个字节。</p>
<h4 id="文件中的空洞"><a href="#文件中的空洞" class="headerlink" title="文件中的空洞"></a>文件中的空洞</h4><p>空洞是由所设置的偏移量超过文件尾端，并写入了某些数据后造成的。</p>
<p>对于没有写过的字节位置，read函数独到的字节是0。</p>
<p>如果使用实用程序复制这个文件，那么所有这些空洞都会被填满，其中所有实际数据字节皆填写为0.</p>
<h3 id="文件截断"><a href="#文件截断" class="headerlink" title="文件截断"></a>文件截断</h3><p>有时候我们需要在文件尾端处截去一些数据以缩短文件。将一个文件的长度截断为0是一个特例，在打开文件时使用O_TRUNC标志就可以做到这一点。为了阶段文件可以调用函数truncate 和ftruncate。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">truncate</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span>* pathname, <span class="keyword">off_t</span> length)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">ftruncate</span><span class="params">(<span class="keyword">int</span> fd, <span class="keyword">off_t</span> length)</span></span>;</span><br><span class="line"><span class="comment">/*两个函数的返回值：若成功，返回0；若出错，返回-1*/</span></span><br></pre></td></tr></table></figure>



<p>这两个函数将一个现有文件长度截为length。如果该文件以前的长度大于length，则超过length以外的数据就不能再访问。如果以前的长度小于length，文件长度将增加，在以前的文件尾端和新的文件尾端之间的数据将读作0（也就是可能在文件中创建了一个空洞）。</p>
<h3 id="函数link、linkat、unlink、unlinkat和remove"><a href="#函数link、linkat、unlink、unlinkat和remove" class="headerlink" title="函数link、linkat、unlink、unlinkat和remove"></a>函数link、linkat、unlink、unlinkat和remove</h3><p>创建一个指向现有文件的链接（硬链接）的方法时使用link函数或linkat函数</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">link</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *existingpath, <span class="keyword">const</span> <span class="keyword">char</span> *newpath)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">linkat</span><span class="params">(<span class="keyword">int</span> efd, <span class="keyword">const</span> <span class="keyword">char</span> *existingpath, <span class="keyword">int</span> nfd, <span class="keyword">const</span> <span class="keyword">char</span> *newpath, <span class="keyword">int</span> flag)</span></span>;</span><br><span class="line"><span class="comment">/* 两个函数的返回值：若成功，返回0；若出错，返回-1 */</span></span><br></pre></td></tr></table></figure>



<p>这两个函数创建一个新目录项newpath，它引用现有文件existingpath。如果newpath已经存在，则返回出错。只创建newpath中的最后一个分量，路径中的其他部分应当已经存在。  </p>
<p>创建新目录项和增加链接计数应当是一个原子操作。  </p>
<p>为了删除一个现有的目录项，可以调用unlink函数。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">unlink</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *pathname)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">unlinkat</span><span class="params">(<span class="keyword">int</span> fd, <span class="keyword">const</span> <span class="keyword">char</span> *path, <span class="keyword">int</span> flag)</span></span>;</span><br><span class="line"><span class="comment">/* 两个函数的返回值：若成功，返回0；若出错，返回-1 */</span></span><br></pre></td></tr></table></figure>



<p>这两个函数删除目录项，并将由pathname所引用文件的链接计数减1。    </p>
<p>只有当链接计数到达0时，文件才能删除。另一个条件也会阻止删除文件的内容——只要有进程打开了该文件，其内容也不能删除。<strong>关闭一个文件时，内核首先检查打开该文件的进程个数；如果这个计数达到0，内核再去检查其链接计数；如果也是0，那么就删除该文件的内容</strong>。</p>
<p>flag参数给出了一种方法，是进程可以改变unlinkat函数的默认行为。当AT_REMVOEDIR标志被设置时，unlinkat函数可以类似于rmdir一样删除目录。如果这个标志被清除，unlinkat与unlink执行同样的操作。  </p>
<p>  我们也可以用 remove 函数接触对一个文件或目录的链接。对于文件，remove的功能与unlink相同。对于目录，remove的功能与rmdir相同。  </p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">remove</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span>* pathname)</span></span>;</span><br><span class="line"><span class="comment">/* 返回值：若成功，返回0；若失败，返回-1 */</span></span><br></pre></td></tr></table></figure>







<h3 id="函数rename和renameat"><a href="#函数rename和renameat" class="headerlink" title="函数rename和renameat"></a>函数rename和renameat</h3><p>文件或者目录能用rename函数或者renameat函数进行重命名。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">rename</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *oldname, <span class="keyword">const</span> <span class="keyword">char</span> *newname)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">renameat</span><span class="params">(<span class="keyword">int</span> oldfd, <span class="keyword">const</span> <span class="keyword">char</span> *oldname, <span class="keyword">int</span> newfd, <span class="keyword">const</span> <span class="keyword">char</span> *newname)</span></span>;</span><br><span class="line"><span class="comment">/* 两个函数返回值：若成功，返回0；若出错，返回-1 */</span></span><br></pre></td></tr></table></figure>

<p>  若newname已经存在：oldname是文件时，newname必须是文件，会将newname删掉并将oldname重命名为newname；oldname是目录时newname必须是目录且是空目录（其下只有.和..），会将newname删掉并将oldname重命名为newname。</p>
<h3 id="符号链接"><a href="#符号链接" class="headerlink" title="符号链接"></a>符号链接</h3><p>符号链接是对一个文件的间接指针，它与硬链接不同，硬链接直接指向文件的i节点。引入符号链接的原因是为了避开硬链接的一些限制。</p>
<ul>
<li>硬链接通常要求链接和文件位于同一文件系统。</li>
<li>只有超级用户才能创建指向目录的硬链接（在第层文件系统支持的情况下）。</li>
</ul>
<p>各函数对符号链接的处理：</p>
<table>
<thead>
<tr>
<th>函数</th>
<th>不跟随符号链接</th>
<th>跟随符号链接</th>
</tr>
</thead>
<tbody><tr>
<td>access</td>
<td></td>
<td>*</td>
</tr>
<tr>
<td>chdir</td>
<td></td>
<td>*</td>
</tr>
<tr>
<td>chmod</td>
<td></td>
<td>*</td>
</tr>
<tr>
<td>chown</td>
<td></td>
<td>*</td>
</tr>
<tr>
<td>creat</td>
<td></td>
<td>*</td>
</tr>
<tr>
<td>exec</td>
<td></td>
<td>*</td>
</tr>
<tr>
<td>lchown</td>
<td>*</td>
<td></td>
</tr>
<tr>
<td>link</td>
<td></td>
<td>*</td>
</tr>
<tr>
<td>lstat</td>
<td>*</td>
<td></td>
</tr>
<tr>
<td>open</td>
<td></td>
<td>*</td>
</tr>
<tr>
<td>opendir</td>
<td></td>
<td>*</td>
</tr>
<tr>
<td>pathconf</td>
<td></td>
<td>*</td>
</tr>
<tr>
<td>readlink</td>
<td>*</td>
<td></td>
</tr>
<tr>
<td>remove</td>
<td>*</td>
<td></td>
</tr>
<tr>
<td>rename</td>
<td>*</td>
<td></td>
</tr>
<tr>
<td>stat</td>
<td></td>
<td>*</td>
</tr>
<tr>
<td>truncate</td>
<td></td>
<td>*</td>
</tr>
<tr>
<td>unlink</td>
<td>*</td>
<td></td>
</tr>
</tbody></table>
<h3 id="创建和读取符号链接"><a href="#创建和读取符号链接" class="headerlink" title="创建和读取符号链接"></a>创建和读取符号链接</h3><p>可以用symlink或symlinkat函数创建一个符号链接。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">symlink</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *actualpath, <span class="keyword">const</span> <span class="keyword">char</span> *sympath)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">symlinkat</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *actualpath, <span class="keyword">int</span> fd, <span class="keyword">const</span> <span class="keyword">char</span> *sympath)</span></span>;</span><br><span class="line"><span class="comment">/* 两个函数的返回值：若成功，返回0；若出错，返回-1 */</span></span><br></pre></td></tr></table></figure>



<p>函数创建了一个指向actualpath的新目录项sympath。在创建此符号链接时，并不要求actualpath已经存在。并且actualpath和sympath并不需要位于同一文件系统中。  </p>
<p>应为open函数跟随符号链接，所以需要一种方法打开该链接本身，并读取该链接中的名字。readlink和readlinkat函数提供了这种功能。  </p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">ssize_t</span> <span class="title">readlink</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *<span class="keyword">restrict</span> pathname, <span class="keyword">char</span> *<span class="keyword">restrict</span> buf, <span class="keyword">size_t</span> bufsize)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">ssize_t</span> <span class="title">readlinkat</span><span class="params">(<span class="keyword">int</span> fd, <span class="keyword">const</span> <span class="keyword">char</span>* <span class="keyword">restrict</span> pathname, <span class="keyword">char</span> *<span class="keyword">restrict</span> buf, <span class="keyword">size_t</span> bufsize)</span></span>;</span><br><span class="line"><span class="comment">/* 两个函数的返回值：若成功，返回读取的字节数；若出错，返回-1 */</span></span><br></pre></td></tr></table></figure>

<p>  两个函数组合了open、read和close的所有操作。如果函数成功执行，则返回读入buf的字节数。在buf中返回的符号链接的内容不以null字节终止。</p>
<h3 id="文件的时间"><a href="#文件的时间" class="headerlink" title="文件的时间"></a>文件的时间</h3><p>每个文件维护3个时间字段，他们的意义于下表所示。  </p>
<table>
<thead>
<tr>
<th>字段</th>
<th>说明</th>
<th>例子</th>
<th>ls(1)选项</th>
</tr>
</thead>
<tbody><tr>
<td>st_atime</td>
<td>文件数据的最后访问时间</td>
<td>read</td>
<td>-u</td>
</tr>
<tr>
<td>st_mtime</td>
<td>文件数据的最后修改时间</td>
<td>write</td>
<td>默认</td>
</tr>
<tr>
<td>st_ctime</td>
<td>i节点状态的最后更改时间</td>
<td>chmod、chown</td>
<td>-c</td>
</tr>
</tbody></table>
<h3 id="函数futimens、utimensat和utimes"><a href="#函数futimens、utimensat和utimes" class="headerlink" title="函数futimens、utimensat和utimes"></a>函数futimens、utimensat和utimes</h3><p>一个文件的访问和修改时间可以用以下几个函数更改。futimens和utimensat函数可以指定纳秒级精度的时间戳。用到的数据结构是与stat函数族相同的timespec结构。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sys/stat.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">futimens</span><span class="params">(<span class="keyword">int</span> fd, <span class="keyword">const</span> struct timespec times[<span class="number">2</span>])</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">utimensat</span><span class="params">(<span class="keyword">int</span> fd, <span class="keyword">const</span> <span class="keyword">char</span> *path, <span class="keyword">const</span> struct timespec times[<span class="number">2</span>], <span class="keyword">int</span> flag)</span></span>;</span><br></pre></td></tr></table></figure>



<p>这两个函数的times数组参数的第一个元素包含访问时间，第二个元素包含修改时间。这两个时间值是日历时间，即自特定时间（1970年1月1日 00:00:00）以来经过的秒数。不足秒的部分用纳秒表示。</p>
<p>时间戳可以按下列4中方式之一进行。</p>
<ol>
<li>如果times参数是一个空指针，则访问使劲按和修改时间两者都设置为当前时间。</li>
<li>如果times参数指向两个timespec结构的数组，任一数组元素的tv_nsec字段的值为UTIME_NOW，相应的事件戳就设置为当前时间，忽略相应的tv_sec字段。</li>
<li>如果times参数指向两个timespec结构的数组，任一数组元素的tv_nsec字段的值为UTIME_OMIT，相应的事件戳保持不变，忽略相应的tv_sec字段。</li>
<li>如果times参数指向两个timespec结构的数组，且tv_nsec字段的值既不是UTIME_NOW也不是UTIME_OMIT，在这种情况下，相应的时间戳设置为相应的时间戳设置为相应的相应的tv_sec和tv_nsec字段的值。</li>
</ol>
<p>futimes和utimeat函数都包含在POSIX.1中，第三个函数utime包含在SUS的XSI扩展中。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sys/time.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">utime</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *pathname, <span class="keyword">const</span> struct timeval time[<span class="number">2</span>])</span></span>;</span><br><span class="line"><span class="comment">/* 函数返回值：若成功，返回0；若出错，返回-1 */</span></span><br></pre></td></tr></table></figure>

<p>utimes函数对路径名进行操作。times参数是指向包含两个时间戳（访问时间和修改时间）元素的数组的指针，两个时间戳是用秒和微妙表示的。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">timeval</span> &#123;</span></span><br><span class="line">    <span class="keyword">time_t</span> tv_sec;	<span class="comment">/* seconds */</span></span><br><span class="line">    <span class="keyword">long</span> tv_usec;	<span class="comment">/* microseconds 微妙 */</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>



<p>我们不能对状态更改时间st_ctime(i节点最近被修改的时间)指定一个值，因为调用utimes函数时，此字段会被自动更新。  </p>
<h3 id="函数mkdir、mkdirat和rmdir"><a href="#函数mkdir、mkdirat和rmdir" class="headerlink" title="函数mkdir、mkdirat和rmdir"></a>函数mkdir、mkdirat和rmdir</h3><p>用mkdir和mkdirat函数创建目录，用rmdir函数删除目录。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sys/stat.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">mkdir</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *pathname, <span class="keyword">mode_t</span> mode)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">mkdirat</span><span class="params">(<span class="keyword">int</span> fd, <span class="keyword">const</span> <span class="keyword">char</span> *pahtname, <span class="keyword">mode_t</span> mode)</span></span>;</span><br><span class="line"><span class="comment">/* 两个 */</span></span><br></pre></td></tr></table></figure>



<p>这两个函数创建一个新的空目录。其中，.和..目录项时自动创建的。所指定的文件访问权限mode由进程的文件模式创建屏蔽字修改。  </p>
<p>对于目录通常至少要设置一个执行权限位，以允许访问该目录中的文件名。</p>
<p>用rmdir函数可以删除一个空目录。空目录是只包含.和..这两项的目录。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">rmdir</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *pathname)</span></span>;</span><br><span class="line"><span class="comment">/* 返回值：若成功，返回0；若出错，返回-1 */</span></span><br></pre></td></tr></table></figure>







<h3 id="读目录"><a href="#读目录" class="headerlink" title="读目录"></a>读目录</h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;dirent.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function">DIR *<span class="title">opendir</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *pathname)</span></span>;</span><br><span class="line"><span class="function">DIR *<span class="title">fdopendir</span><span class="params">(<span class="keyword">int</span> fd)</span></span>;</span><br><span class="line"><span class="comment">/* 两个函数返回值：若成功，返回指针；若出错，返回NULL */</span></span><br><span class="line"></span><br><span class="line"><span class="function">struct dirent *<span class="title">readdir</span><span class="params">(DIR *dp)</span></span>;</span><br><span class="line"><span class="comment">/* 返回值：若成功，返回指针；若在目录尾或出错，返回NULL */</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">rewinddir</span><span class="params">(DIR *dp)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">closedir</span><span class="params">(DIR *dp)</span></span>;</span><br><span class="line"><span class="comment">/* 返回值：若成功，返回0；若出错，返回-1 */</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">long</span> <span class="title">telldir</span><span class="params">(DIR *dp)</span></span>;</span><br><span class="line"><span class="comment">/* 返回值：与dp关联的目录中的当前位置 */</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">seek</span><span class="params">(DIR *dp, <span class="keyword">long</span> loc)</span></span>;</span><br></pre></td></tr></table></figure>



<p>fdopendir函数最早出现在SUSv4中，它提供了一种方法，可以把打开文件描述符装换成目录处理函数需要的DIR结构。</p>
<p>telldir和seekdir函数不是基本POSIX.1标准的组成部分。他们是SUS的XSI扩展，所以可以期望所有符合UNXI系统的实现都会提供这两个函数。</p>
<p>定义在头文件&lt;dirent.h&gt;中的dirent结构与实现有关。实现对此结构所做的定义至少包含下列两个成员：</p>
<ul>
<li>ino_t d_ino;            /* i-node number */</li>
<li>char d_name[]      /* null-terminated filename */</li>
</ul>
<p>DIR结构是一个内部结构，上述7个函数用这个内部结构保存当前正在被读的目录的有关信息。起作用类似于FILE结构。FILE结构由标准I/O库维护。</p>
<p>由opendir和fdopendir返回的指向DIR结构的指针由另外5个函数使用。opendir执行初始化操作，使第一个readdir返回目录中的第一个目录项。DIR结构由fdopendir创建时，readdir返回的第一项取决于传给fdopendir函数的文件描述符相关联的文件偏移量。注意，目录中各目录项的顺序与实现有关。它们通常并不按字符顺序排列。</p>
<h3 id="函数chdir、fchdir和getcwd"><a href="#函数chdir、fchdir和getcwd" class="headerlink" title="函数chdir、fchdir和getcwd"></a>函数chdir、fchdir和getcwd</h3><p>进程调用chdir或fchdir函数可以更改当前工作目录。  </p>
  <figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">chdir</span><span class="params">(<span class="keyword">const</span> <span class="keyword">char</span> *pathname)</span></span>;</span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">fchdir</span><span class="params">(<span class="keyword">int</span> fd)</span></span>;</span><br><span class="line"><span class="comment">/* 两个函数的返回值：若成功，返回0；若失败，返回-1 */</span></span><br></pre></td></tr></table></figure>

<p>​    </p>
<p>获取当前工作目录</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">char</span> *<span class="title">getcwd</span><span class="params">(<span class="keyword">char</span> *buf, <span class="keyword">size_t</span> <span class="built_in">size</span>)</span></span>;</span><br><span class="line"><span class="comment">/* 返回值：若成功，返回buf；若出错，返回NULL */</span></span><br></pre></td></tr></table></figure>



<p>必须向此函数传递两个参数，一个是缓冲区地址buf，另一个是缓冲区的长度size（以字节为单位）。该缓冲区必须有足够的长度以容纳绝对路径名再加上一个终止null字节，否则返回出错。</p>
<h3 id="设备特殊文件"><a href="#设备特殊文件" class="headerlink" title="设备特殊文件"></a>设备特殊文件</h3><p>st_dev和st_rdev这两个字段经常引起混淆。有关规则很简单：</p>
<ul>
<li>每个文件西永所在的存储设备都由其主、次设备号表示。设备号所用的数据类型是基本系统数据类型dev_t。主设备号标识设备驱动程序，有时编码为与其通信的外设板；次设备号标识特定的子设备。一个磁盘驱动器经常包含若干个文件系统。同一磁盘驱动器上的各文件系统通常具有相同的主设备号，但是次设备号却不同。</li>
<li>我们通常可以使用两个宏：major和minor来访问主、次设备号，大多数实现都定义这两个宏。这就意味着我们无需关心这两个数是如何存放在dev_t对象中的。</li>
<li>系统中与每个文件名关联的st_dev值是文件系统的设备号，该文件系统包含了这一文件名以及与其对应的i节点。</li>
<li>只有字符特殊文件和块特殊文件才有st_rdev值。此值包含实际设备的设备号。</li>
</ul>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      
        <div class="post-tags">
          
            <a href="/tags/unix/" rel="tag"># unix</a>
          
            <a href="/tags/%E7%AC%94%E8%AE%B0/" rel="tag"># 笔记</a>
          
        </div>
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2019/10/28/unix/unix%E7%8E%AF%E5%A2%83%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%EF%BC%9A%E9%9D%9E%E7%BC%93%E5%86%B2IO/" rel="next" title="unix环境高级编程：非缓冲IO">
                <i class="fa fa-chevron-left"></i> unix环境高级编程：非缓冲IO
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2019/11/03/unix/unix%E7%8E%AF%E5%A2%83%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B%EF%BC%9A%E6%A0%87%E5%87%86IO%E5%BA%93/" rel="prev" title="unix环境高级编程：标准IO库">
                unix环境高级编程：标准IO库 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <p class="site-author-name" itemprop="name">liuyun</p>
              <p class="site-description motion-element" itemprop="description"></p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/archives/%20%7C%7C%20archive">
              
                  <span class="site-state-item-count">16</span>
                  <span class="site-state-item-name">日志</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/categories/index.html">
                  <span class="site-state-item-count">9</span>
                  <span class="site-state-item-name">分类</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/tags/index.html">
                  <span class="site-state-item-count">21</span>
                  <span class="site-state-item-name">标签</span>
                </a>
              </div>
            

          </nav>

          

          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#函数stat、fstat、fstatat和lstat"><span class="nav-number">1.</span> <span class="nav-text">函数stat、fstat、fstatat和lstat</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#文件类型"><span class="nav-number">2.</span> <span class="nav-text">文件类型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#设置用户ID和组ID"><span class="nav-number">3.</span> <span class="nav-text">设置用户ID和组ID</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#文件访问权限"><span class="nav-number">4.</span> <span class="nav-text">文件访问权限</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#新文件和目录的所有权"><span class="nav-number">5.</span> <span class="nav-text">新文件和目录的所有权</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#函数access和faccessat"><span class="nav-number">6.</span> <span class="nav-text">函数access和faccessat</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#函数umask"><span class="nav-number">7.</span> <span class="nav-text">函数umask</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#函数chmod、fchmod和fchmodat"><span class="nav-number">8.</span> <span class="nav-text">函数chmod、fchmod和fchmodat</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#粘着位"><span class="nav-number">9.</span> <span class="nav-text">粘着位</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#函数chown、fchown、fchownat和lchown"><span class="nav-number">10.</span> <span class="nav-text">函数chown、fchown、fchownat和lchown</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#文件长度"><span class="nav-number">11.</span> <span class="nav-text">文件长度</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#文件中的空洞"><span class="nav-number">11.1.</span> <span class="nav-text">文件中的空洞</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#文件截断"><span class="nav-number">12.</span> <span class="nav-text">文件截断</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#函数link、linkat、unlink、unlinkat和remove"><span class="nav-number">13.</span> <span class="nav-text">函数link、linkat、unlink、unlinkat和remove</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#函数rename和renameat"><span class="nav-number">14.</span> <span class="nav-text">函数rename和renameat</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#符号链接"><span class="nav-number">15.</span> <span class="nav-text">符号链接</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#创建和读取符号链接"><span class="nav-number">16.</span> <span class="nav-text">创建和读取符号链接</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#文件的时间"><span class="nav-number">17.</span> <span class="nav-text">文件的时间</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#函数futimens、utimensat和utimes"><span class="nav-number">18.</span> <span class="nav-text">函数futimens、utimensat和utimes</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#函数mkdir、mkdirat和rmdir"><span class="nav-number">19.</span> <span class="nav-text">函数mkdir、mkdirat和rmdir</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#读目录"><span class="nav-number">20.</span> <span class="nav-text">读目录</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#函数chdir、fchdir和getcwd"><span class="nav-number">21.</span> <span class="nav-text">函数chdir、fchdir和getcwd</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#设备特殊文件"><span class="nav-number">22.</span> <span class="nav-text">设备特殊文件</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">liuyun</span>

  
</div>


  <div class="powered-by">由 <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a> 强力驱动</div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">主题 &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Gemini</a> v5.1.4</div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.4"></script>



  
  


  <script type="text/javascript" src="/js/src/affix.js?v=5.1.4"></script>

  <script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.4"></script>



  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  

  

  
  

  

  

  

<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginModelPath":"assets/","model":{"jsonPath":"/live2dw/assets/miku.model.json"},"display":{"position":"right","width":150,"height":300},"mobile":{"show":false},"log":false,"pluginJsPath":"lib/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>
